import type { HttpTransaction } from '../types';

class TransactionDB {
  private dbName = 'FiddlerTransactions';
  private dbVersion = 1;
  private storeName = 'transactions';
  private db: IDBDatabase | null = null;

  // 初始化数据库
  async init(): Promise<void> {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(this.dbName, this.dbVersion);

      request.onerror = () => {
        reject(new Error('Failed to open IndexedDB'));
      };

      request.onsuccess = () => {
        this.db = request.result;
        resolve();
      };

      request.onupgradeneeded = (event) => {
        const db = (event.target as IDBOpenDBRequest).result;
        
        // 创建对象存储
        if (!db.objectStoreNames.contains(this.storeName)) {
          const store = db.createObjectStore(this.storeName, { keyPath: 'id' });
          
          // 创建索引
          store.createIndex('timestamp', 'createdAt', { unique: false });
          store.createIndex('url', 'request.url', { unique: false });
          store.createIndex('method', 'request.method', { unique: false });
        }
      };
    });
  }

  // 添加或更新交易记录
  async addTransaction(transaction: HttpTransaction): Promise<void> {
    if (!this.db) {
      await this.init();
    }

    return new Promise((resolve, reject) => {
      const transaction_db = this.db!.transaction([this.storeName], 'readwrite');
      const store = transaction_db.objectStore(this.storeName);
      
      const request = store.put(transaction);
      
      request.onsuccess = () => {
        resolve();
      };
      
      request.onerror = () => {
        reject(new Error('Failed to add transaction'));
      };
    });
  }

  // 批量添加交易记录
  async addTransactions(transactions: HttpTransaction[]): Promise<void> {
    if (!this.db) {
      await this.init();
    }

    return new Promise((resolve, reject) => {
      const transaction_db = this.db!.transaction([this.storeName], 'readwrite');
      const store = transaction_db.objectStore(this.storeName);
      
      let completed = 0;
      const total = transactions.length;
      
      if (total === 0) {
        resolve();
        return;
      }
      
      transactions.forEach(transaction => {
        const request = store.put(transaction);
        
        request.onsuccess = () => {
          completed++;
          if (completed === total) {
            resolve();
          }
        };
        
        request.onerror = () => {
          reject(new Error('Failed to add transactions'));
        };
      });
    });
  }

  // 获取最新的交易记录（按时间戳倒序）
  async getLatestTransactions(limit = 100): Promise<HttpTransaction[]> {
    if (!this.db) {
      await this.init();
    }

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([this.storeName], 'readonly');
      const store = transaction.objectStore(this.storeName);
      const index = store.index('timestamp');
      
      // 按时间戳倒序获取
      const request = index.openCursor(null, 'prev');
      const results: HttpTransaction[] = [];
      
      request.onsuccess = (event) => {
        const cursor = (event.target as IDBRequest).result;
        
        if (cursor && results.length < limit) {
          results.push(cursor.value);
          cursor.continue();
        } else {
          resolve(results);
        }
      };
      
      request.onerror = () => {
        reject(new Error('Failed to get transactions'));
      };
    });
  }

  // 获取所有交易记录数量
  async getTransactionCount(): Promise<number> {
    if (!this.db) {
      await this.init();
    }

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([this.storeName], 'readonly');
      const store = transaction.objectStore(this.storeName);
      
      const request = store.count();
      
      request.onsuccess = () => {
        resolve(request.result);
      };
      
      request.onerror = () => {
        reject(new Error('Failed to count transactions'));
      };
    });
  }

  // 清空所有交易记录
  async clearAllTransactions(): Promise<void> {
    if (!this.db) {
      await this.init();
    }

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([this.storeName], 'readwrite');
      const store = transaction.objectStore(this.storeName);
      
      const request = store.clear();
      
      request.onsuccess = () => {
        resolve();
      };
      
      request.onerror = () => {
        reject(new Error('Failed to clear transactions'));
      };
    });
  }

  // 删除旧记录，只保留最新的指定数量
  async keepLatestTransactions(keepCount = 1000): Promise<void> {
    if (!this.db) {
      await this.init();
    }

    const totalCount = await this.getTransactionCount();
    
    if (totalCount <= keepCount) {
      return; // 不需要删除
    }

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([this.storeName], 'readwrite');
      const store = transaction.objectStore(this.storeName);
      const index = store.index('timestamp');
      
      // 获取要删除的记录数量
      const deleteCount = totalCount - keepCount;
      let deleted = 0;
      
      // 按时间戳正序（最旧的在前）
      const request = index.openCursor(null, 'next');
      
      request.onsuccess = (event) => {
        const cursor = (event.target as IDBRequest).result;
        
        if (cursor && deleted < deleteCount) {
          const deleteRequest = cursor.delete();
          
          deleteRequest.onsuccess = () => {
            deleted++;
            if (deleted < deleteCount) {
              cursor.continue();
            } else {
              resolve();
            }
          };
          
          deleteRequest.onerror = () => {
            reject(new Error('Failed to delete old transactions'));
          };
        } else {
          resolve();
        }
      };
      
      request.onerror = () => {
        reject(new Error('Failed to cleanup old transactions'));
      };
    });
  }

  // 关闭数据库连接
  close(): void {
    if (this.db) {
      this.db.close();
      this.db = null;
    }
  }
}

// 创建单例实例
export const transactionDB = new TransactionDB();
export default transactionDB; 